package com.stone.framework.gateway.filter;

import java.util.List;
import java.util.Optional;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;

import com.stone.framework.core.exception.BusinessException;
import com.stone.framework.core.util.Jwts;
import com.stone.framework.gateway.util.ResponseUtil;

import reactor.core.publisher.Mono;

@Component
public class AuthenticationGlobalFilter implements GlobalFilter, Ordered {

    @Value("${stone.auth.skip-paths}")
    private List<String> skipPaths;

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        String path = exchange.getRequest().getURI().getPath();
        String finalPath = path.substring(0, path.indexOf("/", 1)).matches("/stone-[\\w]+-(service|batch)")
            ? path.substring(path.indexOf("/", 1)) : path;
        Optional<String> optional = skipPaths.stream().filter(skipPath -> finalPath.startsWith(skipPath)).findAny();
        if (optional.isPresent()) {
            return chain.filter(exchange);
        }

        String authorization = exchange.getRequest().getHeaders().getFirst(HttpHeaders.AUTHORIZATION);
        if (authorization == null/* || !authorization.matches("Bearer\\s[\\w\\W]+\\.[\\w\\W]+\\.[\\w\\W]+")*/) {
            return ResponseUtil.mono(exchange.getResponse(), HttpStatus.UNAUTHORIZED, "Header 'Authorization' is null");
        }
        String token = authorization.replace("Bearer ", "");
        try {
            Jwts.verify(token, true);
        } catch (BusinessException e) {
            return ResponseUtil.mono(exchange.getResponse(), HttpStatus.UNAUTHORIZED, e.getMessage());
        }

        HttpHeaders headers = HttpHeaders.writableHttpHeaders(exchange.getRequest().getHeaders());
        headers.remove(HttpHeaders.AUTHORIZATION);
        headers.add("token", token);

        return chain.filter(exchange);
    }

    @Override
    public int getOrder() {
        return -50;
    }

}
